﻿using _698._45Tool.Utils;
using Communication;
using Jn698._45Tool.Service;
using Jn698._45Tool.Windows;
using nblTool.parameter;
using nblTool.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using WebFirst.Entities;
using static Communication.MessageGenerationModule;
using static System.Windows.Forms.AxHost;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace Jn698._45Tool
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            this.Load += MainForm_Load;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            var listID = SqlSugarHelper.Db.Queryable<Classid>().Select(c => c.ClassName).ToArray();
            var listDevice = deviceService.Select();
            foreach (var item in listDevice)
            {
                deviceList.Add(item.DeviceAddress, item.DeviceType);
            }
            comboClassData.Items.AddRange(listID);
            comboClassData.SelectedIndex = 0;
            listBoxType.SelectedIndex = 0;

            dt = new DataTable();
            dt.Columns.Add("OI", typeof(string));
            dt.Columns.Add("属性索引", typeof(string));
            dt.Columns.Add("对象名称", typeof(string));
            dataGridViewOAD.AllowUserToAddRows = false;
            dataGridViewOAD.RowHeadersVisible = false;
            dataGridViewNormalData.RowHeadersVisible = false;
            dataGridViewOAD.DataSource = dt;
            dataGridViewOAD.Columns[1].ReadOnly = true;
            dataGridViewOAD.Columns[2].ReadOnly = true;
            dataGridViewOAD.Columns[3].ReadOnly = true;
            dataGridViewOAD.Columns[0].Width = 30;
            dataGridViewOAD.Columns[1].Width = 60;
            dataGridViewOAD.Columns[2].Width = 80;
            //dataGridView1.Columns[3].FillWeight = 600;
            
            ShowDeviceAddress();
            UpdateDataGird();
            GetComboBoxDataChoiceData();
            SetCommOpenFlag(false);
            tabControlData.SelectedIndex = 1;
            //tabControlData.Region = new Region(new RectangleF(this.tabPage3.Left, tabPage3.Top, tabPage3.Width, tabPage3.Height));
            //tabControlData.TabPages.Add(tabPage3);
            tcpHelper.ReceiveDataEvent += ReceiveDataEvent;
            serialPortHelper.ReceiveDataEvent += ReceiveDataEvent;

            #region  自定义组件开始
            //自定义组件实现
            var ch = new DatagridviewCheckboxHeaderCell();
            ch.OnCheckBoxClicked += new DatagridviewcheckboxHeaderEventHander(ch_OnCheckBoxClicked);
            var checkboxCol = this.dataGridViewOAD.Columns[0] as DataGridViewCheckBoxColumn;
            checkboxCol.HeaderCell = ch;
            checkboxCol.HeaderCell.Value = string.Empty;
            #endregion

        }
        #region 属性
        private DeviceService deviceService = new DeviceService();
        private GWCmdMakeUpPlanoldService gWCmdMakeUpPlanoldService = new GWCmdMakeUpPlanoldService();
        private CJDataTypeService cjDataTypeService = new CJDataTypeService();
        private TcpHelper tcpHelper = TcpHelper.Instance;
        private SerialPortHelper serialPortHelper = SerialPortHelper.Instance;
        private object RequestMode = null;
        private DataTable dt = null;
        private Dictionary<int, ObjectID> map = new Dictionary<int, ObjectID>();
        CancellationTokenSource cts = null;
        Dictionary<string, string> deviceList = new Dictionary<string, string>();
        private bool State=false;
        private List<GWCmdMakeUp> gWCmdMakeUps = new List<GWCmdMakeUp>();
        #endregion
        #region 方法
        private void ReceiveDataEvent(object sender, EventArgs e)
        {
            var arg = e as ReceiveDataEventArg;
            //在窗体上显示接收到的报文
            string msgStr = "";
            for (int i = 0; i < arg.Data.Length; i++)
            {
                msgStr += arg.Data[i].ToString("X2") + " ";
            }
            //Console.WriteLine(msgStr);
            this.Invoke(new Action(() => 
            {
                textMsgShow.SelectionStart = textMsgShow.TextLength;
                textMsgShow.SelectionColor = Color.Blue;
                textMsgShow.AppendText($"接收帧({DateTime.Now.ToString()})：{msgStr}\r\n");
                //textMsgShow.Text += $"接收帧({DateTime.Now.ToString()})：{msgStr}\r\n"; 
            }));
            this.Invoke(new Action(() => 
            {
                textMsgShow.SelectionStart = textMsgShow.TextLength;
                textMsgShow.SelectionColor = Color.Orange;
                textMsgShow.AppendText(AnalysisMessage.AnalysisAPDU(arg.Data));
                //textMsgShow.Text += AnalysisMessage.AnalysisAPDU(arg.Data); 
            }));
            
            //SendParamToFrame("接收帧(" + DateTime.Now.ToString() + ")：" + msgStr + "\r\n");
            //SendParamToFrame(AnalysisMessage.AnalysisAPDU(arg.Data));
            
        }
        private void ch_OnCheckBoxClicked(object sender, DatagridviewCheckboxHeaderEventArgs e)
        {
            //失去焦点操作
            dataGridViewOAD.EndEdit();

            //Console.WriteLine(e.CheckedState.ToString());

            //选中事件操作
            if (e.CheckedState)
            {
                for (int i = 0; i < dataGridViewOAD.Rows.Count; i++)
                {
                    dataGridViewOAD.Rows[i].Cells[0].Value = 1;
                }
                //foreach (DataGridViewRow dgvRow in this.dgv.Rows)
                //{
                //    dgvRow.Cells["dataGridViewCheckBoxColumn1"].Value = true;
                //}
            }
            else
            {
                for (int i = 0; i < dataGridViewOAD.Rows.Count; i++)
                {
                    dataGridViewOAD.Rows[i].Cells[0].Value = 0;
                }
                //foreach (DataGridViewRow dgvRow in this.dgv.Rows)
                //{
                //    dgvRow.Cells["dataGridViewCheckBoxColumn1"].Value = 0;
                //}
            }

        }
        private void GetComboBoxDataChoiceData()
        {
            comboBoxDataChoice.Items.Clear();
            Console.WriteLine(listBoxType.SelectedItem.ToString());
            switch (listBoxType.SelectedItem.ToString())
            {
                case "读取请求":
                    comboBoxDataChoice.Items.AddRange(new object[] { "读取一个对象属性请求", "读取多个对象属性请求" });
                    break;
                case "设置请求":
                    comboBoxDataChoice.Items.AddRange(new object[] { "设置一个对象属性请求", "设置多个对象属性请求", "设置后读取多个对象属性请求" });
                    break;
                case "操作请求":
                    comboBoxDataChoice.Items.AddRange(new object[] { "操作一个对象方法请求", "操作若干个对象方法请求", "操作若干个对象方法后读取若干个对象属性请求" });
                    break;
                case "建立应用连接":
                    comboBoxDataChoice.Items.Add("建立应用连接");
                    break;
                case "断开应用连接":
                    comboBoxDataChoice.Items.Add("断开应用连接");
                    break;
                default:
                    break;
            }
            comboBoxDataChoice.SelectedIndex = 0;
        }
        private void UpdateDataGird()
        {

            //添加数据
            DataTable dt = (DataTable)dataGridViewOAD.DataSource;
            dt.Rows.Clear();
            dataGridViewOAD.DataSource = dt;
            map.Clear();
            List<ObjectID> listobject;
            if (comboClassData.SelectedIndex == 0)
            {
                listobject = SqlSugarHelper.Db.Queryable<ObjectID>().Where(o => o.ClientAPDU == (listBoxType.SelectedIndex + 5)).OrderBy(o => o._ObjectID).OrderBy(o => o.AttributeID).ToList();
            }
            else
            {
                listobject = SqlSugarHelper.Db.Queryable<ObjectID>().Where(o => o.Classid == comboClassData.SelectedIndex).Where(o => o.ClientAPDU == (listBoxType.SelectedIndex + 5)).OrderBy(o => o._ObjectID).OrderBy(o => o.AttributeID).ToList();
            }
            int i = 0;
            listobject.ForEach(o =>
            {
                DataRow dataRow = dt.NewRow();
                dataRow[0] = o._ObjectID;
                dataRow[1] = o.AttributeID;
                dataRow[2] = o.ObjectDes;
                dt.Rows.Add(dataRow);
                //map.Add(o._ObjectID + o.AttributeID, o);
                map.Add(i++, o);
            });
        }

        private List<string> GetReadOADSeleced()
        {
            List<string> OADSeleced = new List<string>();
            for (int i = 0; i < dataGridViewOAD.Rows.Count; i++)
            {
                if (dataGridViewOAD.Rows[i].Cells[0].Value != null)
                {
                    if (dataGridViewOAD.Rows[i].Cells[0].Value.Equals(true))
                    {
                        OADSeleced.Add(dataGridViewOAD.Rows[i].Cells[1].Value.ToString() + dataGridViewOAD.Rows[i].Cells[2].Value.ToString().PadLeft(2, '0') + "00");
                    }
                }

            }
            return OADSeleced;
        }
        private string GetSetValue(int dataFormat,string Value)
        {
            string result="";
            switch (dataFormat)
            {
                case 6:
                    int data;
                    if (Int32.TryParse(Value, out data))
                    {
                        result = data.ToString("X8");
                    }
                    break;
                case 9:
                    result = "06" + Value.PadLeft(12, '0');
                    break;
                case 28:
                    if (Value == "系统时间")
                    {
                        result = DateTime.Now.Year.ToString("X4") + DateTime.Now.Month.ToString("X2") + DateTime.Now.Day.ToString("X2") +
                            DateTime.Now.Hour.ToString("X2") + DateTime.Now.Minute.ToString("X2") + DateTime.Now.Second.ToString("X2");
                    }

                    break;
                default:
                    break;
                       
            }
            return result;
        }
        private Dictionary<string,string> GetSetOADSeleced()
        {
            Dictionary<string, string> OADSeleced = new Dictionary<string, string>();
            string OAD = "";
            StringBuilder Value= new StringBuilder();
            int id = 0;
            for (int i = 0; i < dataGridViewOAD.Rows.Count; i++)
            {
                if (dataGridViewOAD.Rows[i].Cells[0].Value != null)
                {
                    if (dataGridViewOAD.Rows[i].Cells[0].Value.Equals(true))
                    {
                        var list = getGWCmdMakeUpList(i);
                        if(int.TryParse(dataGridViewOAD.Rows[i].Cells[2].Value.ToString(), out id) == true)
                        {
                            OAD = dataGridViewOAD.Rows[i].Cells[1].Value.ToString() + id.ToString("X2")+"00";
                        }
                        else
                        {
                            break;
                        }
                        if (list.Count == 1)
                        {
                            GWCmdMakeUp gWCmdMakeUp = list[0];
                            Value.Append(gWCmdMakeUp.DataFormat.ToString("X2").PadLeft(2, '0'));
                            Value.Append(GetSetValue(gWCmdMakeUp.DataFormat, gWCmdMakeUp.DataValue));
                        }
                        else if (list.Count > 1)
                        {
                            Value.Append("02");
                            Value.Append(list.Count.ToString("X2").PadLeft(2,'0'));
                            list.ForEach(g =>
                            {
                                Value.Append(g.DataFormat.ToString("X2").PadLeft(2, '0'));
                                Value.Append(GetSetValue(g.DataFormat, g.DataValue));
                            });
                        }
                        else
                        {
                            Console.WriteLine("无数据项");
                            break;
                        }
                        OADSeleced.Add(OAD,Value.ToString());
                    }
                }

            }
            return OADSeleced;
        }
        private void ReadRequest(List<string> OADSeleced,string DeviceAddress)
        {
            ReadMode mode = (ReadMode)RequestMode;
            if (mode == ReadMode.GetRequestNormal)
            {
                cts = new CancellationTokenSource();
                Task.Run(async () =>
                {
                    foreach (var OAD in OADSeleced)
                    {
                        if (cts.Token.IsCancellationRequested)
                        {
                            
                            this.Invoke(new Action(() =>
                            {
                                textMsgShow.SelectionStart = textMsgShow.TextLength;
                                textMsgShow.SelectionColor = Color.Red;
                                textMsgShow.AppendText($"通讯停止({DateTime.Now.ToString()})\r\n");
                            }));
                            break;
                        }
                        
                        while (true)
                        {
                            byte[] b = MessageGeneration(DeviceAddress, mode, OAD, false);
                            sendMessageShow(b);
                            serialPortHelper.SendDataMethod(b);
                            bool result=false;
                            await Task.Run(() => result=serialPortHelper.DataReceiveFunction());
                            Console.WriteLine(result);
                            break;

                        }

                    }
                }, cts.Token);

            }
            else if (mode == ReadMode.GetRequestNormalList)
            {
                string OADs = "";
                foreach (var OAD in OADSeleced)
                {
                    OADs += OAD;
                }
                byte[] b = MessageGeneration("002001257178", mode, OADs, false);
                //sendMessageShow(b);

                serialPortHelper.SendDataMethod(b);
            }
        }
        private void SetRequest(Dictionary<string, string> map, string DeviceAddress)
        {
            SetMode mode = (SetMode)RequestMode;
            if (mode == SetMode.SetRequestNormal)
            {
                cts = new CancellationTokenSource();
                Task.Run(async () =>
                {
                    foreach (var item in map)
                    {
                        Dictionary<string, string> sendOADData= new Dictionary<string, string>();
                        sendOADData.Add(item.Key, item.Value);
                        if (cts.Token.IsCancellationRequested)
                        {

                            this.Invoke(new Action(() =>
                            {
                                textMsgShow.SelectionStart = textMsgShow.TextLength;
                                textMsgShow.SelectionColor = Color.Red;
                                textMsgShow.AppendText($"通讯停止({DateTime.Now.ToString()})\r\n");
                            }));
                            break;
                        }

                        while (true)
                        {
                            byte[] b = MessageGeneration(DeviceAddress, mode, sendOADData, false);
                            sendMessageShow(b);
                            serialPortHelper.SendDataMethod(b);
                            bool result = false;
                            await Task.Run(() => result = serialPortHelper.DataReceiveFunction());
                            Console.WriteLine(result);
                            break;

                        }

                    }
                }, cts.Token);

            }
            else if (mode == SetMode.SetRequestNormalList)
            {
                string OADs = "";
                
                byte[] b = MessageGeneration("002001257178", mode, map, false);
                //sendMessageShow(b);

                serialPortHelper.SendDataMethod(b);
            }
            else if (mode == SetMode.SetThenGetRequestNormalList)
            {

            }
        }
        private void sendMessageShow(byte[] b)
        {
            string msgStr = "";
            for (int i = 0; i < b.Length; i++)
            {
                msgStr += b[i].ToString("X2") + " ";
            }
            this.Invoke(new Action(() =>
            {
                textMsgShow.SelectionStart = textMsgShow.TextLength;
                textMsgShow.SelectionColor = Color.Green;
                textMsgShow.AppendText($"发送帧({DateTime.Now.ToString()})：{msgStr}\r\n");
            }));
            
        }
        private void SetCommOpenFlag(bool flag)
        {
            btnOpenComm.Enabled = !flag;
            btnCloseComm.Enabled = flag;
        }
        private void OpenComm()
        {
            switch (Comm.selectedCommTypeName)
            {
                case "串口":
                    serialPortHelper.Open();
                    if (serialPortHelper.Status)
                    {
                        State = true;
                        SetCommOpenFlag(State);
                        textBoxCommState.BackColor = Color.LightGreen;
                        textBoxCommState.Text = $"串口{serialPortHelper.serialPortName}已打开！";
                    }
                    else
                    {
                        State = false;
                        SetCommOpenFlag(State);
                        textBoxCommState.Text = $"串口{serialPortHelper.serialPortName}关闭！";
                    }
                    break;
                case "GPRS":
                    tcpHelper.CloseTCP();
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// 帧显示
        /// </summary>
        /// <param name="msg"></param>
        private void SetMsgShow(string msg)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => { textMsgShow.Text = msg; }));
                return;
            }
            textMsgShow.Text = msg;
        }
        private void ShowDeviceAddress()
        {
            foreach (var d in deviceList)
            {
                var item = new ListViewItem(d.Value);
                item.SubItems.Add(d.Key);
                listViewAddress.Items.Add(item);
            }


        }
        private void AddDeviceAddress(Device d)
        {
            var item = new ListViewItem(d.DeviceType);
            item.SubItems.Add(d.DeviceAddress);
            listViewAddress.Items.Add(item);
            
            if (deviceService.Insert(d) > 0)
            {
                Console.WriteLine("增加电表成功");
            }
        }
        
        #endregion


        private void listBoxType_Click(object sender, EventArgs e)
        {
            GetComboBoxDataChoiceData();
            UpdateDataGird();
        }

        private void comboClassData_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (dt != null)
            {
                UpdateDataGird();
            }
        }

        private void btnSendData_Click_1(object sender, EventArgs e)
        {
            
            string DeviceAddress=null;
            foreach (ListViewItem item in listViewAddress.SelectedItems)
            {
                DeviceAddress = item.SubItems[1].Text; 
            }
           
            if (!State)
            {
                MessageBox.Show("请先打开通道");
                return;
            }
            if (DeviceAddress == null)
            {
                MessageBox.Show("请选择设备");
                return;
            }
            switch (listBoxType.SelectedItem.ToString())
            {
                case "读取请求":
                    List<string> OADSeleced = GetReadOADSeleced();
                    if (OADSeleced.Count <= 0)
                    {
                        MessageBox.Show("请选择数据项");
                        return;
                    }
                    ReadRequest(OADSeleced, DeviceAddress);
                    break;
                case "设置请求":
                    Dictionary<string, string> map = GetSetOADSeleced();
                    if (map.Count <= 0)
                    {
                        MessageBox.Show("请选择数据项");
                        return;
                    }
                    SetRequest(map, DeviceAddress);
                    break;
                case "操作请求":

                    break;
                case "建立应用连接":

                    break;
                case "断开应用连接":

                    break;
                default:
                    break;
            }
        }

        private void comboBoxDataChoice_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (comboBoxDataChoice.SelectedItem.ToString())
            {
                case "读取一个对象属性请求":
                    RequestMode = ReadMode.GetRequestNormal;
                    break;
                case "读取多个对象属性请求":
                    RequestMode = ReadMode.GetRequestNormalList;
                    break;
                case "设置一个对象属性请求":
                    RequestMode = SetMode.SetRequestNormal;
                    break;
                case "设置多个对象属性请求":
                    RequestMode = SetMode.SetRequestNormalList;
                    break;
                case "设置后读取多个对象属性请求":
                    RequestMode = SetMode.SetThenGetRequestNormalList;
                    break;
                case "操作一个对象方法请求":
                    RequestMode = ActionMode.ActionRequest;
                    break;
            }
        }

        private void btnSetComm_Click(object sender, EventArgs e)
        {
            Comm comm = new Comm();
            if (comm.ShowDialog() == DialogResult.OK)
            {
                OpenComm();
            }
        }

        private void btnOpenComm_Click(object sender, EventArgs e)
        {
            OpenComm();
        }

        private void btnCloseComm_Click(object sender, EventArgs e)
        {
            State = false;
            switch (Comm.selectedCommTypeName)
            {
                case "串口":
                    serialPortHelper.Close();
                    SetCommOpenFlag(State);
                    textBoxCommState.BackColor = Color.White;
                    textBoxCommState.Text = $"串口{serialPortHelper.serialPortName}关闭！";
                    break;
                case "GPRS":
                    tcpHelper.CloseTCP();
                    SetCommOpenFlag(State);
                    break;
                default:
                    break;
            }

        }

        private void btnAddMeterNo_Click(object sender, EventArgs e)
        {
            /*ListViewItem listViewItem = new ListViewItem("电表");
            listViewItem.SubItems.Add(textBoxMeterNo.Text);
            listViewAddress.Items.Add(listViewItem);*/
           
            
            try
            {
                deviceList.Add(textBoxMeterNo.Text, "电表");
                Device d = new Device();
                d.DeviceAddress= textBoxMeterNo.Text.PadLeft(12,'0');
                d.DeviceType = "电表";
                AddDeviceAddress(d);
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message);
            }
        }

        private void ToolStripMenuItemClearSelectAddress_Click(object sender, EventArgs e)
        {
            
            foreach (ListViewItem item in listViewAddress.SelectedItems)
            {
                listViewAddress.Items.Remove(item);
                deviceList.Remove(item.SubItems[1].Text);
                if (item.SubItems[0].Text.Equals("电表"))
                {
                    Device device = new Device();
                    device.DeviceAddress = item.SubItems[1].Text;
                    device.DeviceType = "电表";
                    deviceService.Delete(device);
                }
            }
        }

        private void ToolStripMenuItemClearAllAddress_Click(object sender, EventArgs e)
        {
            listViewAddress.Items.Clear();
            deviceList.Clear();
            deviceService.DeleteAll();
        }

        private void listViewAddress_Click(object sender, EventArgs e)
        {

            foreach (ListViewItem item in listViewAddress.Items)
            {
                item.BackColor = Color.Empty;
            }
            foreach (ListViewItem item in listViewAddress.SelectedItems)
            {
                item.BackColor = Color.LightGreen;
            }
        }

        private void btnClearMsgShow_Click(object sender, EventArgs e)
        {
            textMsgShow.Clear();
        }

        private void btnCommCancel_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }
        /// <summary>
        /// 获取该OAD的所有设置项
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private List<GWCmdMakeUp> getGWCmdMakeUpList(int index)
        {
            ObjectID objectID = map[index];
            if (objectID == null)
            {
                return null;
            }
           
            return gWCmdMakeUpPlanoldService.Select(objectID);
        }
        private void dataGridViewOAD_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            var list = getGWCmdMakeUpList(e.RowIndex);
            
            dataGridViewNormalData.Rows.Clear();
            if (list!=null&&list.Count > 0)
            {
                tabControlData.SelectedIndex = 0;
                gWCmdMakeUps = list;
                foreach (var item in list)
                {
                    var d = cjDataTypeService.Select(item.DataFormat);
                    dataGridViewNormalData.Rows.Add(new object[] { item.SubItemName, item.DataValue, d.Typename, d.Example, item.Remark });
                }
            }
            else
            {
                tabControlData.SelectedIndex = 1;
            }
           
        }

        private void dataGridViewNormalData_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            GWCmdMakeUp gWCmdMakeUpSelected = gWCmdMakeUps[e.RowIndex];
            gWCmdMakeUpSelected.DataValue = dataGridViewNormalData.Rows[e.RowIndex].Cells[1].Value.ToString();
            gWCmdMakeUpPlanoldService.Update(gWCmdMakeUpSelected);
        }

        private void dataGridViewNormalData_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridViewNormalData.Rows[e.RowIndex].Cells[0].Value.ToString()== "电能表跟随上报模式字")
            {
                MeterFlowerModeBit meterFlowerModeBit = new MeterFlowerModeBit(dataGridViewNormalData.Rows[e.RowIndex].Cells[0].Value.ToString());
                meterFlowerModeBit.ShowDialog();
            }
        }
    }
}
